#include "tp_grupo05.h"


int main() {
  char opt;
  char alvo[MAX_TITULO];
  Registro reg;
  VetSec SKindSecTitulo, SKindSecTipo, SKindSecAutor, SKindSecAno;
  int state = 0;
  Obra novo;
  Obra aux;
  FILE *fpt;
  
  SKindSecTitulo.tam = 0, SKindSecTipo.tam = 0, SKindSecAutor.tam = 0, SKindSecAno.tam = 0; ;
  SKindSecTitulo.tam_disco = 0, SKindSecTipo.tam_disco = 0, SKindSecAutor.tam_disco = 0,SKindSecAno.tam_disco = 0;
  printf("***Bem vindo ao acervo 05***\n");
  ImprimeMenu();
  LoadChaves(&reg);
  LoadRamSec(&SKindSecTitulo, 1,  &aux);
  LoadRamSec(&SKindSecTipo, 2,  &aux);
  LoadRamSec(&SKindSecAutor, 3, &aux);
  LoadRamSec(&SKindSecAno, 4, &aux);
  while(state == 0){ 
    scanf("%c", &opt);
    getchar();
    switch(opt) {  
    case '1':
      fpt = fopen("base05.dat", "a+");
      ScaneiaObra(&novo, &reg);
      JogaRam(&reg, &novo);	
      FilePrint(&novo, &fpt);
      fclose(fpt);
      qsort(SKindSecTitulo.vetor,SKindSecTitulo.tam , sizeof(AtrSec), nosso_strcmp2);
      Gera_Ind_Sec(&novo, &SKindSecTitulo, 1);
      qsort(SKindSecTipo.vetor,SKindSecTipo.tam , sizeof(AtrSec), nosso_strcmp2);
      Gera_Ind_Sec(&novo, &SKindSecTipo, 2);
      qsort(SKindSecAutor.vetor,SKindSecAutor.tam , sizeof(AtrSec), nosso_strcmp2);
      Gera_Ind_Sec(&novo, &SKindSecAutor, 3);
      qsort(SKindSecAno.vetor,SKindSecAno.tam , sizeof(AtrSec), nosso_strcmp2);
      Gera_Ind_Sec(&novo, &SKindSecAno, 4);
      printf("\n");
      ImprimeMenu();
      break;
    case '2':
      printf("Entre com o Titulo da obra a ser procurada:\n");
      /*funcao da biblioteca padrao que ordena o vetor de registros em ordem alfabetica*/
      qsort(reg.vetor, reg.quantidade, sizeof(Chave_prim), nosso_strcmp);
      strcpy(alvo,  CompletaString(alvo, MAX_TITULO));
      strcpy(alvo, Scaneia(alvo, MAX_TITULO));
      Busca(&reg, 0, alvo);
      ImprimeMenu();	
      break;	
    case '3':
    	qsort(reg.vetor, reg.quantidade, sizeof(Chave_prim), nosso_strcmp);
      qsort(SKindSecTitulo.vetor, SKindSecTitulo.tam, sizeof(AtrSec), nosso_strcmp2);
      qsort(SKindSecTipo.vetor, SKindSecTipo.tam, sizeof(AtrSec), nosso_strcmp2);
      qsort(SKindSecAutor.vetor, SKindSecAutor.tam, sizeof(AtrSec), nosso_strcmp2);
      qsort(SKindSecAno.vetor, SKindSecAno.tam, sizeof(AtrSec), nosso_strcmp2);
      BuscaSec(&SKindSecTitulo, &SKindSecTipo, &SKindSecAutor, &SKindSecAno, &reg);
      printf("\n");
      ImprimeMenu();	
      break;
    case '4':
      qsort(reg.vetor, reg.quantidade, sizeof(Chave_prim), nosso_strcmp);
      Lista(&reg);
      printf("\nListagem gerada no arquivo '05.html'\n\n");
      ImprimeMenu();
      break;
    case '5':
      state = 1;
      break;
    default:
      printf("Opção inválida. Tente novamente.\n");
      ImprimeMenu();
      break;    
    }
    
  }
  qsort(reg.vetor, reg.quantidade, sizeof(Chave_prim), nosso_strcmp);
  qsort(SKindSecTitulo.vetor, SKindSecTitulo.tam, sizeof(AtrSec), nosso_strcmp2);
  qsort(SKindSecTipo.vetor, SKindSecTipo.tam, sizeof(AtrSec), nosso_strcmp2);
  qsort(SKindSecAutor.vetor, SKindSecAutor.tam, sizeof(AtrSec), nosso_strcmp2);
  qsort(SKindSecAno.vetor, SKindSecAno.tam, sizeof(AtrSec), nosso_strcmp2);
  GravaChaves(&reg);
  GravaChavesSec(&SKindSecTitulo, &SKindSecTipo, &SKindSecAutor, &SKindSecAno);
  return 0;
}

void ImprimeMenu(){
  
  printf("Entre com '1' para adicionar outras obras ao acervo.\n");
  printf("Entre com '2' para procurar uma pelo titulo completo.\n");
  printf("Entre com '3' para fazer uma busca por outros campos ou por parte do titulo.\n");
  printf("Entre com '4' para listar as obras.\n");
  printf("Entre com '5' para sair do programa.\n");
  
  return;
}

/*funcao VerificaNum:
  Verifica se o char passado como parametro é ou nao um número
  e retorna este número, ou retorna 10 caso não seja um número
*/
int VerificaNum(char i){
  if(i >= '0' && i <= '9') return i - '0';
  return 10;
}

/*Função Scaneia:
  escaneia uma string, recebendo como parametro o campo a ser scaneado e seu tamanho
  ao final da funcao , retorna a string scaneada*/
char *Scaneia(char *campo, int tamanho){
  int cont;
  int ctrl = 1;
  char *pnt;
  char a;
  while(ctrl){
  strcpy(campo, CompletaString(campo, tamanho));
  cont = 0;
  scanf("%c", &campo[cont]);
  while(campo[cont] != '\n'){	
    if (cont > tamanho - 2) {
      /*caso a string esteja completa, joga o excesso de caracteres na variável "a"*/ 
      while (a != '\n') { 				
	scanf("%c", &a);
      }
      break;
    }
    cont++; 
    scanf("%c", &campo[cont]);
  }
  /*substitui o '\n' guardado no vetor por um espaço
   */
  if (cont <= tamanho - 2) campo[cont] = ' ';
  /*Atribui '\0' no final do vetor para garantir que foi demarcado o fim do vetor*/ 
  campo[tamanho-1] = '\0';
  pnt = strstr(campo,"  ");
  if(pnt == NULL){return campo;}
  if((pnt == (campo + cont)) && (pnt != campo)){ctrl = 0;}
  if(ctrl == 1) printf("Entrada invalida.Tente novamente\n"); 
 } 
  return campo;
}

/*função ScaneiaObra:
  Escaneia os campos de string de uma nova Obra usando a função Scaneia.Em seguida, escaneia os campos Ano e Valor verificando se os caracteres digitados são numeros.Por ultimo, escaneia o campo Imagem por meio da função Scaneia.
  Ela utiliza a função busca para verificar se um titulo a ser inserido já existe no banco.
*/  
void ScaneiaObra(Obra *novo, Registro *reg){	
  int aux[MAX_VALOR];
  int cont = 0, ind_aux, tamanho;
  int confirma_busca;
  char alvo[MAX_TITULO];
  char a;
  printf("Entre com o Titulo da obra:\n");
  tamanho = MAX_TITULO;
  strcpy(alvo, Scaneia(alvo, tamanho));
  if(reg->quantidade != 0){
    confirma_busca = Busca(reg, 1, alvo);
    while(confirma_busca == 1){
      printf("Obra ja existente. Digite novo Titulo de obra:\n");
      strcpy(alvo, Scaneia(alvo, tamanho));
      confirma_busca = Busca(reg, 1, alvo);
    }
  }
  strcpy(novo->Titulo, alvo);
  
  printf("Entre com o Tipo da obra:\n");
  tamanho = MAX_TIPO;
  strcpy(novo->Tipo, Scaneia(novo->Tipo, tamanho));
  
  printf("Entre com o Autor da Obra:\n");
  tamanho = MAX_AUTOR;
  strcpy(novo->Autor, Scaneia(novo->Autor, tamanho));
  
  printf("Entre com o Ano da Obra. Caracteres serao desconsiderados:\n");
  scanf("%c", &a);
  while(a != '\n'){
    /*Utiliza VerificaNum para retornar ou o inteiro equivalente,
      passando seu valor para um vetor auxiliar,  ou 10
      caso seja um caractere 		
    */
    ind_aux = VerificaNum(a);
    if (ind_aux < 10) {
      aux[cont] = ind_aux;
      cont++;
      /*Caso o usuario jah tenha entrado com 4 numeros, joga o resto fora
       */
      if (cont  == MAX_ANO){
        while(a != '\n'){
          scanf("%c", &a);
        }         
        break;
      }
    }                     
    scanf("%c", &a);        
  }
  /*zera o vetor da struct, para que ele possa receber o espaço ano
   */
  ind_aux = 0;
  while(ind_aux < MAX_ANO){
    novo->Ano[ind_aux] = 0;
    ind_aux++;
  }
  /*o vetor auxiliar, que contem o ano, é repassado para a struct,
    sendo todos os números jogados para o final do vetor,
    para que o ano, caso tenha menos que 3 digitos, seja completado
    por "0" a esquerda
  */     
  while(cont > 0){
    novo->Ano[ind_aux-1] = aux[cont-1];
    cont--;
    ind_aux--;
  } 
  a = 'a';     
  cont = 0;
  
  printf("Entre com o Valor da Obra. Caracteres serao desconsiderados:\n");
  scanf("%c", &a);
  /*processo identico ao usado para o campo "Ano"
   */
  while(a != '\n'){
    ind_aux = VerificaNum(a);
    if (ind_aux < 10) {
      aux[cont] = ind_aux;
      cont++;
      /*jogando lixo fora
       */
      if (cont  == MAX_VALOR){
        while(a != '\n'){
          scanf("%c", &a);
        }         
        break;
      }
    }                     
    scanf("%c", &a);        
  }
  
  ind_aux = 0;
  while(ind_aux < MAX_VALOR){
    novo->Valor[ind_aux] = 0;
    ind_aux++;
  }
  /*repassando o valor para o vetor struct em processo identico ao do campo Ano
   */     
  while(cont > 0){
    novo->Valor[ind_aux-1] = aux[cont-1];
    cont--;
    ind_aux--;
  }
  /*scan de campo imagem:
    espera-se a entrada padrão, que deve conter 4 numeros e 3 caracteres, 
    não sendo, portanto, verificada a entrada do usuario*/ 
  printf("Entre com a Imagem da Obra:\n");	
  strcpy(novo->Imagem, Scaneia(novo->Imagem, MAX_IMAGEM));
  return;
}

/*Função JogaRam:
  Passa a chave primária e o nrr dos registros inseridos durante a execução para a memória. Caso não exista nenhum registro na mémoria, aloca o vetor de registros na memória em sua 1a chamada e aloca mais 20 espaços sempre que necessário. Ao fim da execução, retorna o registro "reg" atualizado.*/
void JogaRam(Registro *reg, Obra *novo){
  int k;
  k = (int)reg->quantidade/20 + 1;
  if(reg->quantidade%20 == 0){	
    reg->vetor = (Chave_prim *)realloc(reg->vetor, (k)*20*(sizeof(Chave_prim)));
  }
  strcpy(reg->vetor[reg->quantidade].Titulo, novo->Titulo);
  reg->vetor[reg->quantidade].nrr = reg->quantidade;
  reg->quantidade++;
  return;
}	
/*Função FilePrint:
  registra todos os dados contidos na struct em um arquivo
*/
void FilePrint(Obra *novo, FILE **fpt){
  int cont = 0;
  /*registra no arquivo os campos Titulo, Tipo e Autor, 
   */
  fprintf(*fpt, "%s", novo->Titulo);		
  fprintf(*fpt, "%s", novo->Tipo);
  fprintf(*fpt, "%s", novo->Autor);
  /*registra os campos Ano e Valor através de um laço, inteiro por inteiro, 
    já que não se pode usar "%s" por não se tratar de strings
  */
  while(cont	< MAX_ANO){
    fprintf(*fpt, "%d", novo->Ano[cont]);
    cont++;
  }
  cont = 0;
  while(cont < MAX_VALOR){
    fprintf(*fpt, "%d", novo->Valor[cont]);
    cont++;
  }		
  fprintf(*fpt, "%s", novo->Imagem);		
}
/*Função CompletaString:
  a função escreve, em todos os espaços do campo passado como parâmetro, o caractere ' '(espaço) e retorna ao fim de sua execução o vetor zerado. 
*/
char *CompletaString(char *campo, int tamanho){
  int cont;
  cont = 0;
  /*laço que adiciona espaços em todo o vetor
   */
  while(cont < tamanho){
    campo[cont] = ' ';
    cont++;
  }
  campo[tamanho - 1]= '\0';	
  
  return campo;
}
/*Função LoadChaves:
  Carrega as chaves primárias e seus respectivos nrr's do arquivo de chaves para a memória e , no caso de não existir um arquivo de chaves, ele busca as chaves no banco de dados e já adiciona seu nrr. No caso de nenhum dos 2 arquivos existirem, ela simplesmente retorna o struct que foi passado
  como parâmetro, sem alocar seu vetor, mas inicializando, tanto o vetor como o número de registros
*/
void LoadChaves(Registro *reg){
  FILE *arq;
  int k = 1;
  int i = 0;
  reg->quantidade = 0;
  reg->vetor = NULL;
  arq = fopen("chaves05.txt", "r");
  if(arq == NULL){
    arq = fopen("base05.dat", "r");
    if(arq == NULL){
      return;
    }
    while(!feof(arq)){
      if(i%20 == 0){  
        reg->vetor = (Chave_prim *)realloc(reg->vetor, (k++)*20*(sizeof(Chave_prim)));
      } 
      fseek(arq, (i*TAM_REG), SEEK_SET);  
      if(fgets(reg->vetor[i].Titulo, MAX_TITULO, arq) == NULL){
        fclose(arq);
        reg->quantidade = i; 
        return;
      }    
      reg->vetor[i].nrr = i;
      i++;
    }
  }
  while(!feof(arq)){
    if(i%20 == 0){  
      reg->vetor = (Chave_prim *)realloc(reg->vetor, (k++)*20*(sizeof(Chave_prim)));
    } 
    fgets(reg->vetor[i].Titulo, MAX_TITULO, arq);
    fscanf(arq, "%d", &(reg->vetor[i].nrr));
    i++;
  }
  reg->quantidade = i;
  fclose(arq);
  return;
}  
/*Função GravaChaves:
  Função que é chamada no fim da execução do programa para gravar as chaves no arquivo de chaves, bem como seu nrr.
*/
void GravaChaves(Registro *reg){
  
  int i = 0;
  FILE *arq;
  
  arq = fopen("chaves05.txt", "w+");
  while(i < reg->quantidade){
    
    fprintf(arq, "%s", reg->vetor[i].Titulo);
    fprintf(arq, "%d", reg->vetor[i].nrr);			
    i++;
  }
  free(reg->vetor);
  fclose(arq);
  
  return;
  
}	

/*Função Busca:
  Recebe como parâmetro o registro que contem o vetor com as chaves primarias, a chave a ser buscada e um int denominado "caso", que serve para controle da execução determinando se quem está fazendo a busca é o usuário(caso = 0) ou o programa (caso = 1).Se a busca for feita pelo programa, o mesmo não mexe no arquivo html e nem imprime nada na tela.No caso de busca do usuário o registro, se tiver sua pk encontrada, tem seus dados imprimidos no html, caso contrário é impressa a mensagem de "obra não encontrada"  */
int Busca(Registro *reg, int caso, char *alvo){
  FILE *fpt;
  Chave_prim x;
  Chave_prim *aux;
  int y;
  
  strcpy(x.Titulo, alvo);
  aux = bsearch(&x, reg->vetor, reg->quantidade, sizeof(Chave_prim), nosso_strcmp);
  
  if (aux != NULL) {
    if(caso == 1)
      return 1;
    fpt = fopen("base05.dat", "a+");
    y = aux->nrr;
    fseek(fpt, y*TAM_REG, SEEK_SET);
    
    make_html(&fpt, 1, reg);
    fclose(fpt);
    printf("\nBusca gerada no arquivo '05.html'\n\n");
    return 0;
  }
  if (caso == 1)
    return 0;
  if (aux == NULL)
    printf("\nObra não encontrada\n\n");
  
  return 0;
  
}

/*Função Lista:
  usa o vetor de chaves primárias, pegando o nrr de cada uma das chaves e, usando o mesmo, imprime todos os dados de cada uma das obras no html. */

void Lista(Registro *reg){
  
  FILE *fpt;
  
  fpt = fopen("base05.dat", "a+");
  make_html(&fpt, 0, reg);
  fclose(fpt);
  
  return;
  
}

/*Função nosso_strcmp:
  Função de comparacao entre strings que recebe uma string str1 e uma string str2, e compara as duas. Retorna '0' caso as duas strings sejam iguais, '1' ou '-1' caso as duas strings sejam diferentes.
  Utilizada nas funções qsort e bsearch da biblioteca padrão*/
int nosso_strcmp(const void* str1, const void* str2){
  int i=0;
  while(tolower((*(Chave_prim*)str1).Titulo[i]) == tolower((*(Chave_prim*)str2).Titulo[i])){
    if(i == MAX_TITULO-1) return 0;
    i++;
  }
  
  if(tolower((*(Chave_prim*)str1).Titulo[i]) > tolower((*(Chave_prim*)str2).Titulo[i]))
    return 1; 
  
  else if(tolower((*(Chave_prim*)str1).Titulo[i]) < tolower((*(Chave_prim*)str2).Titulo[i]))
    return -1;
  
  return -1;
}

/*Funcao make_html:
  Usa uma variável i para escrever o arquivo através da função fputc, e uma outra variável cont_reg para limitar o número de impressões no arquivo html
  Os vetores inicio_html e fim_html contém os respectivos códigos html que serão escritos no arquivo html.
*/
void make_html (FILE **fpt,int tipo, Registro *reg) {
  int i = 0;
  int x;
  int y;
  int cont_reg = 0;
  
  char *inicio_html;
  char *fim_html;
  FILE *htm;
  
  
  inicio_html = "<html><body><head><title>Resultado da busca no acervo 05</title></head>";
  fim_html = "</table></body></html>";
  
  htm = fopen("05.html", "w+");
  
  fputs(inicio_html, htm);
  if(tipo == 1) x = 1;
  else x = reg->quantidade;
  
  while(cont_reg < x){
    
    /*condicional para, caso o make_html seja chamado na busca, nao realizar o fseek, pois este ja foi chamado na propria funcao busca*/
    if(tipo != 1){
      y = reg->vetor[cont_reg].nrr;
      fseek(*fpt, y*(TAM_REG), SEEK_SET);
    }
    
    /*Impressao do titulo*/
    fputs("Nome: ", htm);
    while(i < MAX_TITULO-1){
      fputc(getc(*fpt),htm);
      i++;
    }
    
    fputs("<br>", htm);
    
    /*Impressao do tipo*/
    i = 0;
    fputs("Tipo: ", htm);
    while(i < MAX_TIPO-1){
      fputc(getc(*fpt),htm);
      i++;
    }
    
    fputs("<br>", htm);
    
    /*Impressao do autor*/
    i = 0;
    fputs("Autor: ", htm);
    while(i < MAX_AUTOR-1){
      fputc(getc(*fpt),htm);
      i++;
    }
    
    fputs("<br>", htm);
    
    /*Impressao do ano*/
    i = 0;
    fputs("Ano: ", htm);
    while(i < MAX_ANO){
      fputc(getc(*fpt),htm);
      i++;
    }
    
    fputs("<br>", htm);
    
    /*Impressao do valor*/
    i = 0;
    fputs("Valor: ", htm);
    while(i < MAX_VALOR){
      fputc(getc(*fpt),htm);
      i++;
    }
    
    fputs("<br>", htm);
    
    /*Impressao da imagem*/
    i = 0;
    fputs("Imagem: ", htm);
    fputs("<br>", htm);
    fputs("<img src=img/", htm);
    while(i <= 5){
      fputc(getc(*fpt),htm);
      i++;
    }
    fputs(".", htm);
    i = 0;
    while(i <= 2){
      fputc(getc(*fpt),htm);
      i++;
    }
    i = 0;
    fputs(">", htm);
    
    fputs("<br>", htm);
    
    cont_reg++;
    
  }
  
  fputs(fim_html, htm);
  
  fclose(htm);
  return;
  
}

/*Função Gera_Ind_Sec
Função que é utilizada quando o usuário insere uma obra e para carregar as obras da base quando não existe arquivo de chaves secundárias
As informações a serem passadas para disco que não tem relação com as chaves ficam na estrutura Obra, já as informações das chaves secundárias ficam na estrutura VetSec, enquanto que a variável cod contém apenas uma identificação para qual tipo de chave secundária usar.
*/
void Gera_Ind_Sec(Obra *novo, VetSec *SKindSec, int cod){

  FILE *PKindSec;
  int cont_vetor;
  int tamSK, k, cont_disco, i = -1;
  char *pch = NULL;
  char titulo[MAX_TITULO];
  
/*Temos que passar o item a ser procurado para a estrutura Procurado por causa dos parâmetro pedidos pela nossa função de comparação nosso_strcmp. A estrutura aux conterá o apontador resultante da bsearch
*/
  AtrSec Procurado;
  AtrSec *aux;
  
  if(SKindSec->tam == 0){
  SKindSec->vetor = NULL;
  }
	

  cont_vetor = SKindSec->tam;
  cont_disco = SKindSec->tam_disco;
  
  strcpy(titulo, CompletaString(titulo, MAX_TITULO));

 if(cod != 4){
  	if(cod == 1){
  		strcpy(titulo, novo->Titulo);
  		PKindSec = fopen("Chave_sec05titulo.txt", "a+");
	}
	if(cod == 2){
	  	strcpy(titulo, novo->Tipo);
  		PKindSec = fopen("Chave_sec05tipo.txt", "a+");
	}
	if(cod == 3){
	  	strcpy(titulo, novo->Autor);
  		PKindSec = fopen("Chave_sec05autor.txt", "a+");
	}  	
  	pch = strtok(titulo," ");
  	while(pch != NULL){
  	 k = (int)(cont_vetor)/20 + 1;	
     
  	 if(cont_vetor%20 == 0){
    		SKindSec->vetor = (AtrSec *)realloc(SKindSec->vetor, (k++)*20*(sizeof(AtrSec)));
  	 }
    
    tamSK = strlen(pch);
    strcpy(Procurado.nome, CompletaString(Procurado.nome, MAX_TITULO));
    strcpy(Procurado.nome, pch);
    
    aux = bsearch(&Procurado, SKindSec->vetor, cont_vetor, sizeof(AtrSec), nosso_strcmp2);
	
/*Caso não tenha um mesmo nome de chave secundária do mesmo tipo. É adicionado no arquivo de PKs a palavra correspondente com o apontador -1.
*/
    if(aux == NULL){
      
      /*------------------------------*/
      /*ARMAZENAR A PARTE DA SK NA RAM*/
      strcpy(SKindSec->vetor[cont_vetor].nome, CompletaString(SKindSec->vetor[cont_vetor].nome, MAX_TITULO));
      SKindSec->vetor[cont_vetor].tam_string = tamSK;
      strcpy(SKindSec->vetor[cont_vetor].nome, pch);
      SKindSec->vetor[cont_vetor].pos = cont_disco;
      /*------------------------------*/
      
      /*-----------------------------*/
      /*GRAVAR A PARTE DA PK EM DISCO*/
      fprintf(PKindSec, "%s", novo->Titulo);
      fprintf(PKindSec, "%08d", i);
      /*-----------------------------*/
      cont_vetor++;
      cont_disco++;
    }
	
/*Caso a busca retorne que já existe uma mesma palavra na chave secundária no respectivo tipo, é só atualizado o arquivo de chaves primárias*/
    else{
      fprintf(PKindSec, "%s", novo->Titulo);
      fprintf(PKindSec, "%08d", aux->pos);
      aux->pos = cont_disco;
      cont_disco++;       
    }
    pch = strtok(NULL," ");   
  }
 }
 else{ 
 	k = (int)(cont_vetor)/20 + 1;	
 	if(cont_vetor%20 == 0){
	  SKindSec->vetor = (AtrSec *)realloc(SKindSec->vetor, (k++)*20*(sizeof(AtrSec)));
	}
	/*CASO 4 - ANO*/
	strcpy(Procurado.nome, CompletaString(Procurado.nome, MAX_TITULO));
	PKindSec = fopen("Chave_sec05ano.txt", "a+");
	for(k = 0;k<4;k++){
	  Procurado.nome[k] = novo->Ano[k] + '0';
	}
	Procurado.nome[k] = '\0';
	aux = bsearch(&Procurado, SKindSec->vetor, cont_vetor, sizeof(AtrSec), nosso_strcmp2);	
	if(aux == NULL){
	  strcpy(SKindSec->vetor[cont_vetor].nome, CompletaString(SKindSec->vetor[cont_vetor].nome, MAX_TITULO));
	  SKindSec->vetor[cont_vetor].tam_string = 4;
	  strcpy(SKindSec->vetor[cont_vetor].nome, Procurado.nome);
	  SKindSec->vetor[cont_vetor].pos = cont_disco;
	  
	  fprintf(PKindSec, "%s", novo->Titulo);
	  fprintf(PKindSec, "%08d", i);

	  cont_disco++;
	  cont_vetor++;
	}
	else{
	  fprintf(PKindSec, "%s", novo->Titulo);
	  fprintf(PKindSec, "%08d", aux->pos);
	  
	  aux->pos = cont_disco;
	  cont_disco++;
	}
 }
 fclose(PKindSec);
 SKindSec->tam_disco = cont_disco;
 SKindSec->tam = cont_vetor;	    
 return;
}


/*Função GravaChavesSec
Função que basicamente grava os registros das chaves secundárias que estavam na RAM para os respectivos arquivos. Assim como para os índices primários, é chamada no final da execução do programa*/
void GravaChavesSec(VetSec *Titulo, VetSec *Tipo, VetSec *Autor, VetSec *Ano){
  FILE *t, *a, *an, *ti;
  int cont = 0;
  t = fopen("Chave_sec05tipoRAM.txt", "w+");
  a = fopen("Chave_sec05autorRAM.txt", "w+");
  an = fopen("Chave_sec05anoRAM.txt", "w+");
  ti = fopen("Chave_sec05tituloRAM.txt", "w+");
  
  fprintf(t, "%d ", Tipo->tam_disco);
  while(cont < Tipo->tam){
    fprintf(t, "%d %s %d ",Tipo->vetor[cont].tam_string, Tipo->vetor[cont].nome, Tipo->vetor[cont].pos);
    cont++;
  }	
  
  cont = 0;
  fprintf(a, "%d ", Autor->tam_disco);
  while(cont < Autor->tam){
    fprintf(a, "%d %s %d ",Autor->vetor[cont].tam_string, Autor->vetor[cont].nome, Autor->vetor[cont].pos);
	cont++;
  }
  
   cont = 0;
   fprintf(ti, "%d ", Titulo->tam_disco);
  while(cont < Titulo->tam){
    fprintf(ti, "%d %s %d ",Titulo->vetor[cont].tam_string, Titulo->vetor[cont].nome, Titulo->vetor[cont].pos);
    cont++;
  }
  
  cont = 0;
  fprintf(an, "%d ", Ano->tam_disco);
  while(cont < Ano->tam){
    fprintf(an, "%d %s %d ",Ano->vetor[cont].tam_string, Ano->vetor[cont].nome, Ano->vetor[cont].pos);
    cont++;
  }
  fclose(t);
  fclose(a);
  fclose(an);
  fclose(ti);

  return;
}

void BuscaSec(VetSec *Titulo, VetSec *Tipo, VetSec *Autor, VetSec *Ano, Registro *reg){
  int cmd;
  char campo[201];
  printf("Entre com '1' para busca por titulo.\n");
  printf("Entre com '2' para busca por tipo.\n");
  printf("Entre com '3' para busca por autor\n");
  printf("Entre com '4' para busca por ano.\n");
  scanf("%d", &cmd);
  getchar();
  switch(cmd){
  case 1:
    printf("Entre com a palavra a ser buscada.\n");
    scanf("%s", campo);
    buscaXXX(Titulo,campo,1, reg);
    break;
  case 2:
    printf("Entre com a palavra a ser buscada.\n");
    scanf("%s", campo);
    buscaXXX(Tipo,campo, 2, reg);
    break;
  case 3:
    printf("Entre com a palavra a ser buscada.\n");
    scanf("%s", campo);
    buscaXXX(Autor,campo, 3, reg);
    break;
  case 4:
    printf("Entre com a palavra a ser buscada.\n");
    scanf("%s", campo);
    buscaXXX(Ano,campo, 4, reg);
    break;
  }
  return;
}  
  
		  
void buscaXXX(VetSec *X, char *campo, int i, Registro *reg){
  FILE *arq;
  int k, l;
  char c;
  Registro B;
  Chave_prim alvo2;
  Chave_prim *aux2;
  AtrSec *aux;
  AtrSec alvo;
  strcpy(alvo.nome, CompletaString(alvo.nome, MAX_TITULO));
  strcpy(alvo.nome, campo);
  getchar();
  switch(i){
  case 1:
    arq = fopen("Chave_sec05titulo.txt", "r");
    break;				
  case 2:
    arq = fopen("Chave_sec05tipo.txt", "r");
    break;
  case 3:
    arq = fopen("Chave_sec05autor.txt", "r");
    break;
  case 4:
    arq = fopen("Chave_sec05ano.txt", "r");
    break;
  } 
  aux = bsearch(&alvo, X->vetor, X->tam, sizeof(AtrSec), nosso_strcmp2);  
  if(aux == NULL){
  	printf("nada encontrado\n");
  	return;
  }	
  B.quantidade = 0;
  k = aux->pos;
  l = 1;
  B.vetor = NULL;

  while(k != -1){	 		
  	 if(B.quantidade%20 == 0){
  	 	B.vetor = (Chave_prim *)realloc(B.vetor, (l++)*20*(sizeof(Chave_prim)));
  	 }	
    fseek(arq, k*(MAX_TITULO + 7), SEEK_SET);
    strcpy(B.vetor[B.quantidade].Titulo, CompletaString(B.vetor[B.quantidade].Titulo, MAX_TITULO));
    fgets(B.vetor[B.quantidade].Titulo, MAX_TITULO, arq);
	 strcpy(alvo2.Titulo, B.vetor[B.quantidade].Titulo);
	 aux2 = bsearch(&alvo2, reg->vetor, reg->quantidade, sizeof(Chave_prim), nosso_strcmp);
	 B.vetor[B.quantidade].nrr = aux2->nrr;
	 B.quantidade++;
  	 fscanf(arq, "%08d", &k);
  }
  qsort(B.vetor, B.quantidade, sizeof(Chave_prim), nosso_strcmp);
  ImprimeBusca(&B);	
  Lista(&B);
  printf("deseja excluir alguma obra?(s/n)\n");
  scanf("%c", &c);
  getchar();
  if(c == 's'){
  	Remocao(reg, &B);
  	 qsort(B.vetor, B.quantidade, sizeof(Chave_prim), nosso_strcmp);	
  	 Lista(&B);
  }
  free(B.vetor);
  return;
}

/*Função LoadRamSec
Carrega as estruturas VetSec correspondentes aos índices secundários. É passado como parâmetro uma estrutura VetSec,  esta podendo ser do título, tipo, autor ou ano. O outro parâmentro int tipo é para identificar qual arquivo será aberto e carregado para a RAM. O terceiro parâmetro Obra *novo é somente para usarmos a função Gera_Ind_Sec.*/
void LoadRamSec (VetSec *Vet, int tipo, Obra *novo) {
	FILE *arq;
	int cont = 0;
	int l = 0;
	int k = 1;
	int j;
	int i = 0;
	int limite;
	Vet->vetor = NULL;
	
	if (tipo == 1) 
		arq = fopen("Chave_sec05tituloRAM.txt", "r");
	if (tipo == 2) 
		arq = fopen("Chave_sec05tipoRAM.txt", "r");
	if (tipo == 3) 
		arq = fopen("Chave_sec05autorRAM.txt", "r");
	if (tipo == 4) 
		arq = fopen("Chave_sec05anoRAM.txt", "r");
	
/*Se não existir arquivo de chaves secundárias, elas são carregadas diretamente da base, e essa não existir também, a função é interrompida*/
	if(arq == NULL) {
		arq = fopen("base05.dat", "r");
		if(arq == NULL) return;
		
/*A variável limite será usada no fseek para pegar cada registro da base, e dependendo do tipo de chave que será carregada, o espaço andado no arquivo de base será diferente*/
		if (tipo == 1) limite = 0;
		if (tipo == 2) limite = 0;
		if (tipo == 3) limite = 300;
		if (tipo == 4) limite = 425;
		
		fseek(arq, 0, SEEK_SET);

		while(!feof(arq)){
			switch(tipo) {
			
				case 1:
					if( fgets(novo->Titulo, MAX_TITULO, arq) == NULL) {
						fclose(arq);
						return;	
					}
					qsort(Vet->vetor, Vet->tam, sizeof(AtrSec), nosso_strcmp2);
					Gera_Ind_Sec(novo, Vet, tipo);
					break;
				case 2:
					if( fgets(novo->Titulo, MAX_TITULO, arq) == NULL){
					fclose(arq);
						return;
					}
					fgets(novo->Tipo, MAX_TIPO, arq);
					qsort(Vet->vetor, Vet->tam, sizeof(AtrSec), nosso_strcmp2);
					Gera_Ind_Sec(novo, Vet, tipo);
					break;
				case 3:
					if( fgets(novo->Titulo, MAX_TITULO, arq) == NULL){
					fclose(arq);
						return;
					}
					fseek(arq, l*TAM_REG + limite, SEEK_SET);
					fgets(novo->Autor, MAX_AUTOR, arq);
					qsort(Vet->vetor, Vet->tam, sizeof(AtrSec), nosso_strcmp2);
					Gera_Ind_Sec(novo, Vet, tipo);
					break;
				case 4:
					if( fgets(novo->Titulo, MAX_TITULO, arq) == NULL){
					fclose(arq);
						return;
					}
					fseek(arq, l*TAM_REG + limite, SEEK_SET);
					cont = 0;
					while(cont < 4){
						fscanf(arq, "%1d", &novo->Ano[cont]);
						cont++;
					}
					qsort(Vet->vetor, Vet->tam, sizeof(AtrSec), nosso_strcmp2);
					Gera_Ind_Sec(novo, Vet, tipo);
					break;
			}
			l++;
			fseek(arq, l*TAM_REG, SEEK_SET);
		}
		fclose(arq);
		return;
	}
	
/*Caso exista já um arquivo de chaves secundárias, ele é carregado para a RAM*/
	else{
		fscanf(arq, "%d", &Vet->tam_disco);
		fgetc(arq);
		while(fscanf(arq, "%d", &j) != EOF){
			if(i%20 == 0){
				Vet->vetor =(AtrSec *)realloc(Vet->vetor, (k++)*20*sizeof(AtrSec));
			}
			Vet->vetor[i].tam_string = j;
			fgetc(arq);
			strcpy(Vet->vetor[i].nome, CompletaString(Vet->vetor[i].nome, MAX_TITULO));
			fgets(Vet->vetor[i].nome, Vet->vetor[i].tam_string + 1, arq);
			fgetc(arq);
			fscanf(arq, "%d", &Vet->vetor[i].pos);
			fgetc(arq);
			i++;
		}
		Vet->tam = i;
		fclose(arq);
		return;
	}
}

void Remocao(Registro *reg, Registro *B){
int i;
Chave_prim *aux;
	printf("Entre com o numero correspondente:\n");
	scanf("%d", &i);
	getchar();
	if(i >= B->quantidade){
		printf("operação inválida\n");
		return;
	}
	aux = bsearch(&(B->vetor[i]),reg->vetor, reg->quantidade, sizeof(Chave_prim), nosso_strcmp);
	strcpy(aux->Titulo, reg->vetor[reg->quantidade - 1].Titulo);
	aux->nrr = reg->vetor[reg->quantidade - 1].nrr;
	reg->quantidade--;
	strcpy(B->vetor[i].Titulo, B->vetor[B->quantidade -1].Titulo);
	B->vetor[i].nrr = B->vetor[B->quantidade - 1].nrr;
	B->quantidade--;
	return;
}

void ImprimeBusca(Registro *reg){
int i = 0;
int ind;
char *pnt;
	while(i < reg->quantidade){
		pnt = strstr(reg->vetor[i].Titulo, "  ");
		printf("%d - ", i);
		ind = 0;
		while((reg->vetor[i].Titulo + ind) < pnt){
			printf("%c", reg->vetor[i].Titulo[ind]);
			ind++;
		}
		printf("\n");	
		i++;
	}
}

int nosso_strcmp2(const void* str1, const void* str2){
  int i=0;
  while(tolower((*(AtrSec*)str1).nome[i]) == tolower((*(AtrSec*)str2).nome[i])){
    if(i == MAX_TITULO-1) return 0;
    i++;
  }
  
  if(tolower((*(AtrSec*)str1).nome[i]) > tolower((*(AtrSec*)str2).nome[i]))
    return 1; 
  
  else if(tolower((*(AtrSec*)str1).nome[i]) < tolower((*(AtrSec*)str2).nome[i]))
    return -1;
  
  return -1;
}
